package rt

import (
	"fmt"
	"kumachan/standalone/util/richtext"
	"kumachan/interpreter/lang/common/source"
)


type RuntimeError struct {
	Content    interface{}
	FrameAddr  uintptr
	Location   *ExecutionLocation
}
type ExecutionLocation struct {
	Function  *FunctionEntity
	InstPtr   LocalAddr
}
func (loc ExecutionLocation) SourceLocation() source.Location {
	return source.Location {
		File: loc.Function.Info.Location.File,
		Pos:  loc.Function.Code.Position[loc.InstPtr],
	}
}

func (err *RuntimeError) Message() richtext.Block {
	var err_desc string
	switch e := err.Content.(type) {
	case error:
		err_desc = e.Error()
	case fmt.Stringer:
		err_desc = e.String()
	case string:
		err_desc = e
	default:
		err_desc = "unknown error"
	}
	var b richtext.Block
	b.WriteLine(fmt.Sprintf("*** Frame {0x%x}", err.FrameAddr), richtext.TAG_EM)
	b.WriteLine(err_desc)
	if err.Location != nil {
		var loc = source.Location {
			File: err.Location.Function.Info.Location.File,
			Pos:  err.Location.Function.Code.Position[err.Location.InstPtr],
		}
		return loc.FormatMessage(b)
	} else {
		return b
	}
}

func (err *RuntimeError) ConsoleText() string {
	return err.Message().RenderConsole()
}

func (err *RuntimeError) Error() string {
	return fmt.Sprintf("runtime error: %v", err.Content)
}


